package com.ideaaedi.zoo.foundation.filter;

import com.ideaaedi.zoo.foundation.properties.ZooFoundationProperties;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
import org.springframework.boot.autoconfigure.AutoConfigurationMetadata;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.util.CollectionUtils;

import javax.annotation.Nonnull;
import java.util.Arrays;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * AutoConfiguration过滤器
 *
 * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img
 * src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
 * @since 1.0.0
 */
@ConditionalOnMissingBean(name = "foundationAutoConfigurationImportFilter")
public class FoundationAutoConfigurationImportFilter implements AutoConfigurationImportFilter, EnvironmentAware {
    
    private ZooFoundationProperties zooFoundationProperties;
    
    @Override
    public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
        boolean[] matched = new boolean[autoConfigurationClasses.length];
        Arrays.fill(matched, true);
        if (zooFoundationProperties == null) {
            return matched;
        }
        Map<String, Boolean> excludeAutoconfigures = zooFoundationProperties.getExcludeAutoconfigures();
        Set<String> needExcludeAutoconfigureSet = excludeAutoconfigures.entrySet()
                .stream()
                .filter(x -> x != null && BooleanUtils.isTrue(x.getValue()))
                .map(Map.Entry::getKey)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(needExcludeAutoconfigureSet)) {
            return matched;
        }
        if (needExcludeAutoconfigureSet.size() > 0) {
            for (int i = 0; i < autoConfigurationClasses.length; i++) {
                String autoConfigurationClass = autoConfigurationClasses[i];
                if (needExcludeAutoconfigureSet.contains(autoConfigurationClass)) {
                    matched[i] = false;
                }
            }
        }
        return matched;
    }
    
    
    @Override
    public void setEnvironment(@Nonnull Environment environment) {
        try {
            if (zooFoundationProperties == null) {
                zooFoundationProperties = Binder.get(environment).bind(ZooFoundationProperties.PREFIX, ZooFoundationProperties.class).get();
            }
        } catch (NoSuchElementException ignore) {
            // ignore. may be no relative config
        }
    }
}
